import requests
from typing import Dict, Any

class TravelService:
    def __init__(self):
        self.base_url = "https://api.map.baidu.com/directionlite/v1"
        self.ak = "TWBzmMaW5GOdMDPTwBAsXXJgqcX36mWz" # 从环境变量获取百度地图AK
        self.mode_urls = {
            "driving": f"{self.base_url}/driving",
            "riding": f"{self.base_url}/riding",
            "walking": f"{self.base_url}/walking",
            "transit": f"{self.base_url}/transit"
        }

    def get_travel_plan(
        self,
        start_point: str,
        end_point: str,
        travel_mode: str = "driving",
        route_preference: str = "0"
    ) -> Dict[str, Any]:
        """
        获取路线规划
        :param start_point: 起点（格式：纬度,经度）
        :param end_point: 终点（格式：纬度,经度）
        :param travel_mode: 出行方式（driving-驾车、riding-骑行、walking-步行、transit-公交）
        :param route_preference: 路线偏好（仅驾车模式下有效）
            0：常规路线
            1：不走高速
            2：避开拥堵
            3：距离最短
            4：花费最少
            5：大路优先
        :return: 路线规划结果
        """
        if travel_mode not in self.mode_urls:
            raise ValueError(f"不支持的出行方式: {travel_mode}")

        # 构建请求参数
        params = {
            "ak": self.ak,
            "origin": start_point,
            "destination": end_point,
            "coord_type": "bd09ll",  # 百度经纬度坐标
            "ret_coordtype": "bd09ll"  # 返回百度经纬度坐标
        }


        # 驾车模式下添加路线偏好参数
        if travel_mode == "driving" and route_preference:
            params["tactics"] = route_preference

        print(params)
        
        # 发送请求
        try:
            response = requests.get(self.mode_urls[travel_mode], params=params)
            response.raise_for_status()  # 检查响应状态
            result = response.json()

            if result.get("status") != 0:
                raise Exception(result.get("message", "获取路线规划失败"))

            if(travel_mode == "driving" or travel_mode == "walking" or travel_mode == "riding"):
                return self._format_response(result, travel_mode)
            else:
                return self._format_transit_response(result)

        except requests.RequestException as e:
            raise Exception(f"请求百度地图API失败: {str(e)}")

    def _format_response(self, result: Dict[str, Any], travel_mode: str) -> Dict[str, Any]:
        """
        格式化响应数据
        :param result: 百度地图API返回的原始数据
        :param travel_mode: 出行方式
        :return: 格式化后的数据
        """
        try:
            route_result = result["result"]
            routes = route_result["routes"][0]  # 取第一条路线

            # 提取共同字段
            formatted_result = {
                "distance": routes["distance"],  # 总距离（米）
                "duration": routes["duration"],  # 预计时间（秒）
                "steps": []
            }

            # 处理路线步骤
            for step in routes["steps"]:
                formatted_step = {
                    "instruction": step["instruction"],  # 路线描述
                    "distance": step["distance"],        # 该段距离
                    "duration": step["duration"],        # 该段预计时间
                    "path": step["path"],               # 路径坐标点
                }

                # 驾车模式下添加路况信息
                if travel_mode == "driving" and "traffic_condition" in step:
                    formatted_step["traffic_condition"] = step["traffic_condition"]

                formatted_result["steps"].append(formatted_step)

            return formatted_result

        except (KeyError, IndexError) as e:
            raise Exception(f"解析路线数据失败: {str(e)}")
        

    def _format_transit_response(self, result):
        """格式化公交路线规划的返回结果"""
        if not result or 'result' not in result:
            return None
            
        routes = result['result'].get('routes', [])
        if not routes:
            return None
            
        formatted_routes = []
        for route in routes:
            formatted_route = {
                'distance': route.get('distance', 0),  # 总距离
                'duration': route.get('duration', 0),  # 总时间
                'price': route.get('price', 0),  # 票价
                'steps': [],
                'line_price': route.get('line_price', [])  # 各段路线票价
            }
            
            # 处理每个步骤
            for step_group in route.get('steps', []):
                for step in step_group:
                    formatted_step = {
                        'type': step.get('type', 0),  # 5-步行, 3-公交
                        'distance': step.get('distance', 0),
                        'duration': step.get('duration', 0),
                        'instruction': step.get('instruction', ''),
                        'path': step.get('path', ''),
                        'start_location': step.get('start_location', {}),
                        'end_location': step.get('end_location', {}),
                    }
                    
                    # 如果是公交步骤，添加车辆信息
                    if step.get('type') == 3:
                        vehicle = step.get('vehicle', {})
                        formatted_step['vehicle'] = {
                            'name': vehicle.get('name', ''),
                            'start_name': vehicle.get('start_name', ''),
                            'end_name': vehicle.get('end_name', ''),
                            'start_time': vehicle.get('start_time', ''),
                            'end_time': vehicle.get('end_time', ''),
                            'stop_num': vehicle.get('stop_num', 0),
                            'total_price': vehicle.get('total_price', 0),
                            'direct_text': vehicle.get('direct_text', ''),
                            'line_color': vehicle.get('line_color', '')
                        }
                    
                    formatted_route['steps'].append(formatted_step)
            
            formatted_routes.append(formatted_route)
        
        return {
            'routes': formatted_routes
        }

    def geocode(self, address: str) -> Dict[str, float]:
        """
        地理编码服务：将地址转换为经纬度坐标
        :param address: 地址
        :return: 经纬度坐标
        """

        print(address)
        url = "https://api.map.baidu.com/geocoding/v3/"
        params = {
            "ak": self.ak,
            "address": address,
            "output": "json",
            "ret_coordtype": "bd09ll"
        }
 
        try:
            response = requests.get(url, params=params)
            response.raise_for_status()
            result = response.json()

            if result.get("status") != 0:
                raise Exception(result.get("message", "地理编码失败"))

            location = result["result"]["location"]
            return {
                "lat": location["lat"],
                "lng": location["lng"]
            }

        except requests.RequestException as e:
            raise Exception(f"请求地理编码服务失败: {str(e)}") 